import { Rectangle } from '../math';
/**
 * 布局样式类，用于配置DisplayObject的布局信息
 *
 * @class
 * @memberof PIXI
 */
export default class LayoutStyle
{
    // eslint-disable-next-line valid-jsdoc
    /**
     * @param {object} [options] - The optional renderer parameters
     * @param {number|string} [options.x=0] - x偏移值，在使用对齐方式计算出横向坐标后，再增加x的偏移量，x可以为百分比字符串，表示
     * 偏移父节点宽度的百分比
     * @param {number|string} [options.y=0] - y偏移值，在使用对齐方式计算出纵向坐标后，再增加y的偏移量，y可以为百分比字符串，表示
     * 偏移父节点高度的百分比
     * @param {number|string} [options.width=1] - 设计宽度，可以为百分比的字符串，表示为父节点宽度的百分之多少，例width:'30%'表示
     * 父节点30%的宽度
     * @param {number|string} [options.height=1] - 设计高度，可以为百分比的字符串，表示为父节点高度的百分之多少，例height:'30%'表示
     * 父节点30%的高度
     * @param {string} [options.align='left'] - 横向对齐方式，相对于父节点，值类型为['left','center','right']
     * `'left'` 左对齐
     * `'center'` 居中
     * `'right'` 右对齐
     * @param {string} [options.valign='top'] - 横向对齐方式，相对于父节点，值类型为['top','middle','bottom']
     * `'top'` 顶部对齐
     * `'middle'` 居中
     * `'bottom'` 底部对齐
     * @example
     * new LayoutStyle({align:'center',x:-50,valign:'bottom',y:50,width:'100%',height:'100%'});
     * // 该例为横向居中对齐，然后向左便宜50像素，宽度为父节点的宽度
     * // 纵向底部对齐，再向下移动50像素，高度为父节点高度
     */
    constructor(options)
    {
        /**
         * The default options, so we mixin functionality later.
         * @member {object}
         * @protected
         */
        this._options = options = Object.assign({
            x: 0,
            y: 0,
            align:'left',
            valign:'top',
            width:1,
            height:1,
        }, options);
        this._val = {
            x:0,y:0,w:1,h:1,
            _x_israte:false,
            _y_israte:false,
            _w_israte:false,
            _h_israte:false,
        }
        this._dirty = true;
        this._offset_dirty = false;
    }

    /**
     * x偏移值，在使用对齐方式计算出横向坐标后，再增加x的偏移量，x可以为百分比字符串，表示偏移父节点宽度的百分比
     * @member {number|string}
     */
    get x(){return this._val.x}
    set x(v){ this._options.x = v;this._dirty = true; }

    /**
     * y偏移值，在使用对齐方式计算出纵向坐标后，再增加y的偏移量，y可以为百分比字符串，表示偏移父节点高度的百分比
     * @member {number|string}
     */
    get y(){return this._val.y}
    set y(v){ this._options.y = v;this._dirty = true; }

    /**
     * 设计宽度，可以为百分比的字符串，表示为父节点宽度的百分之多少，例width:'30%'表示父节点30%的宽度
     * @member {number|string}
     */
    get w(){return this._val.w}
    set w(v){ this._options.width = v;this._dirty = true; }

    /**
     * 设计宽度，可以为百分比的字符串，表示为父节点宽度的百分之多少，例width:'30%'表示父节点30%的宽度
     * @member {number|string}
     */
    get width(){return this._val.w}
    set width(v){ this._options.width = v;this._dirty = true; }

    /**
     * 设计高度，可以为百分比的字符串，表示为父节点高度的百分之多少，例height:'30%'表示父节点30%的高度
     * @member {number|string}
     */
    get h(){return this._val.h}
    set h(v){ this._options.height = v;this._dirty = true; }

    /**
     * 设计高度，可以为百分比的字符串，表示为父节点高度的百分之多少，例height:'30%'表示父节点30%的高度
     * @member {number|string}
     */
    get height(){return this._val.h}
    set height(v){ this._options.height = v;this._dirty = true; }

    /**
     * 横向对齐方式，相对于父节点
     * `'left'` 左对齐
     * `'center'` 居中
     * `'right'` 右对齐
     * @member {string}
     */
    get align(){ return this._options.align;}
    set align(v){ this._options.align = v;this._dirty = true;}

    /**
     * 横向对齐方式，相对于父节点
     * `'top'` 顶部对齐
     * `'middle'` 居中
     * `'bottom'` 底部对齐
     * @member {string}
     */
    get valign(){ return this._options.valign;}
    set valign(v){ this._options.valign = v;this._dirty = true;}

    /**
     * 数据是否脏了，脏了需要重新计算layout
     * @member {boolean}
     */
    get dirty(){ return this._dirty||this._offset_dirty;}
    set dirty(v){ this._dirty = v;}

    /**
     * 偏移是否脏了，脏了需要重新计算便宜值
     * @member {boolean}
     */
    get offset_dirty(){ return this._offset_dirty;}
    set offset_dirty(v){ this._offset_dirty = v;this._dirty = this._dirty||v;}

    /**
     * 传入父节点，根据选项计算真实的布局信息
     * @param {number} parent_width 父节点宽度
     * @param {number} parent_height 父节点高度
     * @param {PIXI.Rectangle} rect - Optional rectangle to store the result of the bounds calculation
     * @return {PIXI.Rectangle} 返回计算后的信息
     */
    get_layout(parent_width,parent_height,rect){
        if(this._offset_dirty)
            throw '偏移地址发生了变更，但是未执行重新计算过程，请执行update_offset进行更正数据！！';
        var opt = this._options;
        var val = this._val;
        let aw = parent_width;
        let ah = parent_height;
        var v = null;
        if(this._dirty){
            v = this.__get_val(opt.x);
            val.x_israte = v.is_rate;
            val.x = v.v;

            v = this.__get_val(opt.y);
            val.y_israte = v.is_rate;
            val.y = v.v;

            v = this.__get_val(opt.width);
            val.w_israte = v.is_rate;
            val.w = v.v;

            v = this.__get_val(opt.height);
            val.h_israte = v.is_rate;
            val.h = v.v;
            this._dirty = false;
        }

        var r = rect||new Rectangle();
        r.width = val.w_israte?val.w*aw:val.w;
        r.height = val.h_israte?val.h*ah:val.h;

        if(opt.align == 'right')
            r.x = aw - r.width;
        else if (opt.align == 'center')
            r.x = (aw - r.width)/2.0;
        else
            r.x = 0;

        if (opt.valign == 'bottom')
            r.y = ah - r.height;
        else if (opt.valign == 'middle')
            r.y = (ah - r.height) / 2.0;
        else
            r.y = 0;

        r.x += val.x_israte?val.x*aw:val.x;
        r.y += val.y_israte?val.y*ah:val.y;
        return r;
    }

    __get_val(s){
        var ts = typeof(s)
        if (ts == 'string') {
        if(s.indexOf('%')!=-1)
            return { v: parseInt(s) / 100.0, is_rate:true}
        else
            return { v: parseFloat(s), is_rate:false}
        } else if (ts == 'number') {
        return { v: s, is_rate:false}
        }
        else return {v:0,is_rate:false}
    }

    /**
     * 根据当前坐标和父节点的大小，以设定的对齐方式进行偏移坐标修正
     * @param {number} px 当前对象的位置x
     * @param {number} py 当前对象的位置y
     * @param {number} pw 当前对象的宽度
     * @param {number} ph 当前对象的高度
     * @param {number} parent_width 父节点宽度
     * @param {number} parent_height 父节点高度
     */
    update_offset(px,py,pw,ph,parent_width,parent_height) {
        let aw = parent_width;
        let ah = parent_height;
        const opt = this._options;
        var val = this._val;

        if (opt.align == 'right')
        val.x = val.x_israte ? (aw - pw-px) / aw : (aw - pw - px);
        else if (opt.align == 'center')
        val.x = (aw - px) / 2.0 / (val.x_israte?aw:1)
        else
        val.x = val.x_israte?px/aw:px;

        if (opt.valign == 'bottom')
        val.y = val.y_israte ? (ah - ph - py) / ah : (ah - ph - py);
        else if (opt.valign == 'middle')
        val.y = (ah - ph) / 2.0 / (val.y_israte ? ah : 1)
        else
        val.y = val.y_israte ? py / ah : py

        this._offset_dirty = false;
    }
}